/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
<template>
  <div class="datax-model">
    <template v-if="taskType === 'DATAX'">
      <m-list-box>
        <div slot="text">{{$t('Custom template')}}</div>
        <div slot="content">
          <label class="label-box">
            <div style="padding-top: 5px;">
              <el-switch v-model="enable" @change="_onSwitch" :disabled="isDetails"></el-switch>
            </div>
          </label>
        </div>
      </m-list-box>
      <template v-if="!enable">
        <m-list-box>
          <div slot="text">{{$t('Datasource')}}</div>
          <div slot="content">
            <m-datasource
              ref="refDs"
              @on-dsData="_onDsData"
              :supportType="['MYSQL','POSTGRESQL', 'ORACLE', 'SQLSERVER']"
              :data="{ type:dsType,datasource:datasource }">
            </m-datasource>
          </div>
        </m-list-box>
        <m-list-box>
          <div slot="text">{{$t('SQL Statement')}}</div>
          <div slot="content">
            <div class="form-mirror">
              <textarea
                id="code-sql-mirror"
                name="code-sql-mirror"
                style="opacity: 0;">
              </textarea>
              <a class="ans-modal-box-max">
                <em class="el-icon-full-screen" @click="setEditorVal"></em>
              </a>
            </div>
          </div>
        </m-list-box>
        <m-list-box>
          <div slot="text">{{$t('TargetDataBase')}}</div>
          <div slot="content">
            <m-datasource
              ref="refDt"
              @on-dsData="_onDtData"
              :supportType="['MYSQL','POSTGRESQL', 'ORACLE', 'SQLSERVER']"
              :data="{ type:dtType,datasource:datatarget }">
            </m-datasource>
          </div>
        </m-list-box>
        <m-list-box>
          <div slot="text">{{$t('TargetTable')}}</div>
          <div slot="content">
            <el-input
              type="input"
              size="small"
              v-model="targetTable"
              :placeholder="$t('Please enter the table of target')">
            </el-input>
          </div>
        </m-list-box>
        <m-list-box>
          <div slot="text">{{$t('TargetDataBase')}}{{$t('Pre Statement')}}</div>
          <div slot="content">
            <m-statement-list
              ref="refPreStatements"
              @on-statement-list="_onPreStatements"
              :statement-list="preStatements">
            </m-statement-list>
          </div>
        </m-list-box>
        <m-list-box>
          <div slot="text">{{$t('TargetDataBase')}}{{$t('Post Statement')}}</div>
          <div slot="content">
            <m-statement-list
              ref="refPostStatements"
              @on-statement-list="_onPostStatements"
              :statement-list="postStatements">
            </m-statement-list>
          </div>
        </m-list-box>
        <m-list-box>
          <div slot="text">
            <span>{{$t('SpeedByte')}}</span>
          </div>
          <div slot="content">
            <m-select-input v-model="jobSpeedByte" :list="[0,1,10,50,100,512].map(item => ('' + item))">
            </m-select-input>
            <span>({{$t('0 means unlimited by byte')}})</span>
          </div>
        </m-list-box>
        <m-list-box>
          <div slot="text">
            <span>{{$t('SpeedRecord')}}</span>
          </div>
          <div slot="content">
            <m-select-input v-model="jobSpeedRecord" :list="[0,500,1000,1500,2000,2500,3000].map(item => (''+item))">
            </m-select-input>
            <span>({{$t('0 means unlimited by count')}})</span>
          </div>
        </m-list-box>
      </template>
      <template v-else>
        <m-list-box>
          <div slot="text">json</div>
          <div slot="content">
            <div class="form-mirror">
              <textarea
                id="code-json-mirror"
                name="code-json-mirror"
                style="opacity: 0;">
              </textarea>
            </div>
          </div>
        </m-list-box>
        <m-list-box>
          <div slot="text">{{$t('Custom Parameters')}}</div>
          <div slot="content">
            <m-local-params
                    ref="refLocalParams"
                    @on-local-params="_onLocalParams"
                    :udp-list="localParams"
                    :hide="false">
            </m-local-params>
          </div>
        </m-list-box>
      </template>
      <m-list-box>
        <div slot="text">{{$t('Running Memory')}}</div>
        <div slot="content">
          <span >{{$t('Min Memory')}}</span>
          <m-select-input v-model="xms" :list="[1,2,3,4].map(item => ('' + item))">
          </m-select-input>
          <span>&nbsp;&nbsp;&nbsp;G &nbsp;&nbsp;</span>
          <span >{{$t('Max Memory')}}</span>
          <m-select-input v-model="xmx" :list="[1,2,3,4].map(item => ('' + item))">
          </m-select-input>
          <span>&nbsp;&nbsp;&nbsp;G</span>
        </div>
      </m-list-box>
    </template>
    <template  v-if="taskType === 'INPUT'">
      <m-list-box>
        <div slot="text">{{$t('Datasource')}}</div>
        <div slot="content">
          <el-select size="small" style="width: calc(50% - 10px)" @change="datasourceTypeChange('source')" v-model="dsType" placeholder="请选择数据源类型">
            <el-option v-for="item of datasourceTypeList" :label="item.label" :value="item.value"></el-option>
          </el-select>
          <el-select size="small" class="mar-l-20" style="width: calc(50% - 10px)" @change="datasourceChange('source')" v-model="datasource" placeholder="请选择数据源">
            <el-option v-for="item of datasources" :label="item.name" :value="item.id"></el-option>
          </el-select>
        </div>
      </m-list-box>
      <m-list-box>
        <div slot="text">表</div>
        <div slot="content">
          <el-select size="small" class="dis-b" @change="tableChange('source')"  v-model="sourceTable" placeholder="请选择表">
            <el-option v-for="item of tables" :label="item" :value="item"></el-option>
          </el-select>
        </div>
      </m-list-box>
      <m-list-box>
        <div slot="text">字段</div>
        <div slot="content">
          <el-select class="dis-b" size="small" v-model="sourceCloumns" multiple placeholder="请选择">
            <el-option
              v-for="item in columns"
              :key="item.value"
              :label="item.name"
              :value="item.value">
            </el-option>
          </el-select>
          <!-- <el-select size="small" class="dis-b" @change="tableChange('source')"  v-model="sourceTable" placeholder="请选择表">
            <el-option v-for="item of tables" :label="item" :value="item"></el-option>
          </el-select> -->
        </div>
      </m-list-box>
    </template>
    <template  v-if="taskType === 'OUTPUT'">
      <m-list-box>
        <div slot="text">{{$t('Datasource')}}</div>
        <div slot="content">
          <el-select size="small" style="width: calc(50% - 10px)" @change="datasourceTypeChange('target')" v-model="dtType" placeholder="请选择数据源类型">
            <el-option v-for="item of datasourceTypeList" :label="item.label" :value="item.value"></el-option>
          </el-select>
          <el-select size="small" class="mar-l-20" style="width: calc(50% - 10px)" @change="datasourceChange('target')" v-model="datatarget" placeholder="请选择数据源">
            <el-option v-for="item of datasources" :label="item.name" :value="item.id"></el-option>
          </el-select>
        </div>
      </m-list-box>
      <m-list-box>
        <div slot="text">表</div>
        <div slot="content">
          <el-select size="small" class="dis-b" @change="tableChange('target')"  v-model="targetTable" placeholder="请选择表">
            <el-option v-for="item of tables" :label="item" :value="item"></el-option>
          </el-select>
        </div>
      </m-list-box>
      <m-list-box>
        <div slot="text">字段</div>
        <div slot="content">
          <el-select class="dis-b" size="small" v-model="targetCloumns" multiple placeholder="请选择">
            <el-option
              v-for="item in columns"
              :key="item.value"
              :label="item.name"
              :value="item.value">
            </el-option>
          </el-select>
          <!-- <el-select size="small" class="dis-b" @change="tableChange('source')"  v-model="sourceTable" placeholder="请选择表">
            <el-option v-for="item of tables" :label="item" :value="item"></el-option>
          </el-select> -->
        </div>
      </m-list-box>
    </template>
    <el-dialog  v-if="taskType === 'DATAX'" append-to-body
      :visible.sync="scriptBoxDialog"
      width="80%">
      <m-script-box :item="item" @getSriptBoxValue="getSriptBoxValue" @closeAble="closeAble"></m-script-box>
    </el-dialog>
  </div>
</template>
<script>
  import { mapActions } from 'vuex'
  import * as _ from 'lodash'
  import i18n from '@/lang'
  import mListBox from './_source/listBox'
  import mScriptBox from './_source/scriptBox'
  import mDatasource from './_source/datasource'
  import mLocalParams from './_source/localParams'
  import mStatementList from './_source/statementList'
  import disabledState from '@/mixins/disabledState'
  import mSelectInput from '../_source/selectInput'
  import codemirror from '@/view-module/dolphin-scheduler/pages/resource/pages/file/pages/_source/codemirror'
  import datasourceTypeList from '@/config/datasourceTypeList';

  let editor
  let jsonEditor

  export default {
    name: 'datax',

    data () {
      return {
        datasources: [],
        tables: [],
        columns: [],
        datasourceTypeList: datasourceTypeList,

        targetCloumns: [],
        sourceCloumns: [],
        // Data Custom template
        enable: false,
        // Data source type
        dsType: '',
        // data source
        datasource: '',
        // Data source type
        dtType: '',
        // data source
        datatarget: '',
        // Return to the selected data source
        rtDatasource: '',
        // Return to the selected data target
        rtDatatarget: '',
        // Sql statement
        sql: '',
        json: '',
        sourceTable: '',
        // target table
        targetTable: '',
        // Pre statements
        preStatements: [],
        // Post statements
        postStatements: [],
        // speed byte
        jobSpeedByte: '0',
        // speed record
        jobSpeedRecord: '1000',
        // Custom parameter
        localParams: [],
        customConfig: 0,
        // jvm memory xms
        xms: '1',
        // jvm memory xms
        xmx: '1',
        scriptBoxDialog: false,
        item: ''
      }
    },
    mixins: [disabledState],
    props: {
      backfillItem: Object,
      createNodeId: Number,
      taskType: String
    },
    methods: {
      ...mapActions('datasource', ['getDatasourcesList' , 'getTablesByDatasourceId' , 'getColumns' , 'recursionDir' , 'recursionDirFile']),
      ...mapActions('dag' , ['saveTask' , 'updateTask' , 'verifDAGName' , 'getProcessDetails']), 
      datasourceTypeChange(type , noClear){
        if(!noClear){
          this[type === 'source' ? 'datasource' : 'datatarget'] = null;
          this[type === 'source' ? 'sourceTable' : 'targetTable'] = '';
        }
        let name = type === 'source' ? 'dsType' : 'dtType';
        let dType = TouchList[name];
        if(this[`datasourceTypeChange_${dType}`]){
          this[`datasourceTypeChange_${dType}`](type , noClear);
        }else{
          this.defaultDatasourceTypeChange(type , noClear);
        }
      },
      // default
      defaultDatasourceTypeChange(type , noClear){
    
        let name = type === 'source' ? 'dsType' : 'dtType';
        if(!this.datasources[this[name]]){
          this.getDatasourcesList({
            type: this[name]
          }).then(
            res => {
              this.datasources = res.data || [];
            }
          )
        }
      },
      datasourceChange(type , noClear){
        if(!noClear){
          this[type === 'source' ? 'sourceTable' : 'targetTable'] = '';
        }
        let name = type === 'source' ? 'dsType' : 'dtType';
        let dType = this[name];
        if(dType !== 'KAFKA'){
          if(this[`datasourceChange_${dType}`]){
            this[`datasourceChange_${dType}`](type , noClear);
          }else{
            this.defaultDatasourceChange(type , noClear);
          }
        }else{
          this.useDatasourceChangeKAFKA();
        }
      },
      defaultDatasourceChange(type , noClear){
        let datasourceName = type === 'source' ? 'datasource' : 'datatarget';
        if((type === 'source' && this.dsType !== 'FTP') || (type === 'target' && this.dtType !== 'FTP')){
          if(!this.tables[this[datasourceName]]){
            this.getTablesByDatasourceId(this[datasourceName]).then(
              res => {
                if(res.data.data){
                  this.tables = res.data.data || [];
                }
              }
            )
          }
        }
        // if((type === 'source' && this.dsType === 'FTP') || (type === 'target' && this.dtType === 'FTP')){
        //   (type === 'target' ? this.recursionDir : this.recursionDirFile)({
        //     datasourceId: this.form.processDefinitionJson.tasks[0].params[datasourceName],
        //     directory: '/'
        //   }).then(
        //     res => {
        //       this.recursionDirs[type] = this.resetRecursionDir(res.data.data.children , type);
        //     }
        //   )
        // }
      },
      tableChange(type , callback){

        this.columns = [];
        let values = {};
        let datasourceName = type === 'source' ? 'datasource' : 'datatarget';
        let tableName = type === 'source' ? 'sourceTable' : 'targetTable';
        if(this[datasourceName] && this[tableName]){
          this.getColumns({
            datasourceId: this[datasourceName],
            tableName: this[tableName]
          }).then(
            res => {
              if(res.data.data){
                let data = [];
                res.data.data.forEach(
                  v => {
                    data.push({
                      name: v,
                      value: v
                    })
                    if(type === 'target'){
                      values[v] = '';
                    }
                  }
                )
                this.columns = data;
                // if(type === 'target'){
                //   this.columns.values = values;
                // }
              }
              // this.useDatasourceChangeKAFKA();
              // callback && callback(type);
            }
          )
        }
      },
      setEditorVal () {
        this.item = editor ? editor.getValue() : '';
        this.scriptBoxDialog = true
      },
      getSriptBoxValue (val) {
        editor.setValue(val)
      },
      closeAble () {
        // this.scriptBoxDialog = false
      },
      _onSwitch (is) {
        if (is) {
          this.customConfig = 1
          setTimeout(() => {
            this._handlerJsonEditor()
          }, 200)
        } else {
          this.customConfig = 0
          setTimeout(() => {
            this._handlerEditor()
          }, 200)
        }
      },
      /**
       * return data source
       */
      _onDsData (o) {
        this.dsType = o.type
        this.rtDatasource = o.datasource
      },
      /**
       * return data target
       */
      _onDtData (o) {
        this.dtType = o.type
        this.rtDatatarget = o.datasource
      },
      /**
       * return pre statements
       */
      _onPreStatements (a) {
        this.preStatements = a
      },
      /**
       * return post statements
       */
      _onPostStatements (a) {
        this.postStatements = a
      },
      /**
       * return localParams
       */
      _onLocalParams (a) {
        this.localParams = a
      },
      /**
       * verification
       */
      _verification () {
        if (this.customConfig) {
          if (!jsonEditor.getValue()) {
            this.$message.warning(`${i18n.$t('Please enter a JSON Statement(required)')}`)
            return false
          }

          // localParams Subcomponent verification
          if (!this.$refs.refLocalParams._verifProp()) {
            return false
          }

          // storage
          this.$emit('on-params', {
            customConfig: this.customConfig,
            json: jsonEditor.getValue(),
            localParams: this.localParams,
            xms: +this.xms,
            xmx: +this.xmx
          })
          return true
        } else {
          if(this.taskType === 'DATAX'){
            if (!editor.getValue()) {
              this.$message.warning(`${i18n.$t('Please enter a SQL Statement(required)')}`)
              return false
            }
            // datasource Subcomponent verification
            if (!this.$refs.refDs._verifDatasource()) {
              return false
            }

            // datasource Subcomponent verification
            if (!this.$refs.refDt._verifDatasource()) {
              return false
            }

            if (!this.targetTable) {
              this.$message.warning(`${i18n.$t('Please enter a Target Table(required)')}`)
              return false
            }

            // preStatements Subcomponent verification
            if (!this.$refs.refPreStatements._verifProp()) {
              return false
            }

            // postStatements Subcomponent verification
            if (!this.$refs.refPostStatements._verifProp()) {
              return false
            }
          }

          let dataxParams = {};

          if(this.taskType === 'DATAX'){
            dataxParams = {
              xms: +this.xms,
              xmx: +this.xmx,
              sql: editor ? editor.getValue() : '',
            }
          }

          // storage
          this.$emit('on-params', {
            customConfig: this.customConfig,
            dsType: this.dsType,
            dataSource: this.datasource || 1,
            dtType: this.dtType,
            dataTarget: this.datatarget || 1,
            sourceTable: this.sourceTable,
            targetTable: this.targetTable,
            jobSpeedByte: parseInt(this.jobSpeedByte) * 1024,
            jobSpeedRecord: parseInt(this.jobSpeedRecord),
            preStatements: this.preStatements,
            postStatements: this.postStatements,
            localParams: this.localParams,
            targetCloumns: this.targetCloumns,
            sourceCloumns: this.sourceCloumns,
            ...dataxParams
          })
          return true
        }
      },
      /**
       * Processing code highlighting
       */
      _handlerEditor () {
        this._destroyEditor()

        // editor
        editor = codemirror('code-sql-mirror', {
          mode: 'sql',
          readOnly: this.isDetails
        })

        this.keypress = () => {
          if (!editor.getOption('readOnly')) {
            editor.showHint({
              completeSingle: false
            })
          }
        }

        // Monitor keyboard
        editor.on('keypress', this.keypress)

        editor.on('changes', () => {
          this._cacheParams()
        })

        editor.setValue(this.sql)

        return editor
      },
      _handlerJsonEditor () {
        this._destroyJsonEditor()

        // jsonEditor
        jsonEditor = codemirror('code-json-mirror', {
          mode: 'json',
          readOnly: this.isDetails
        })

        this.keypress = () => {
          if (!jsonEditor.getOption('readOnly')) {
            jsonEditor.showHint({
              completeSingle: false
            })
          }
        }

        // Monitor keyboard
        jsonEditor.on('keypress', this.keypress)

        jsonEditor.on('changes', () => {
          // this._cacheParams()
        })

        jsonEditor.setValue(this.json)

        return jsonEditor
      },
      _cacheParams () {
        let dataxParams = {};

        if(this.taskType === 'DATAX'){
          dataxParams = {
            xms: +this.xms,
            xmx: +this.xmx,
            sql: editor ? editor.getValue() : '',
          }
        }
        this.$emit('on-cache-params', {
          dsType: this.dsType,
          dataSource: this.datasource || 1,
          dtType: this.dtType,
          dataTarget: this.datatarget || 1,
          sql: editor ? editor.getValue() : '',
          sourceTable: this.sourceTable,
          targetTable: this.targetTable,
          jobSpeedByte: parseInt(this.jobSpeedByte) * 1024,
          jobSpeedRecord: parseInt(this.jobSpeedRecord),
          preStatements: this.preStatements,
          postStatements: this.postStatements,
          localParams: this.localParams,
          targetCloumns: this.targetCloumns,
          sourceCloumns: this.sourceCloumns,
          ...dataxParams
        })
      },
      _destroyEditor () {
        if (editor) {
          editor.toTextArea() // Uninstall
          editor.off($('.code-sql-mirror'), 'keypress', this.keypress)
          editor.off($('.code-sql-mirror'), 'changes', this.changes)
        }
      },
      _destroyJsonEditor () {
        if (jsonEditor) {
          jsonEditor.toTextArea() // Uninstall
          jsonEditor.off($('.code-json-mirror'), 'keypress', this.keypress)
          jsonEditor.off($('.code-json-mirror'), 'changes', this.changes)
        }
      }
    },
    created () {
      let o = this.backfillItem
      console.log(this.taskType);
      // Non-null objects represent backfill
      if (!_.isEmpty(o)) {
        // set jvm memory
        this.xms = '' + (o.params.xms || 1)
        this.xmx = '' + (o.params.xmx || 1)
        // backfill
        if (o.params.customConfig === 0) {
          this.customConfig = 0
          this.enable = false
          this.dsType = o.params.dsType || ''
          this.datasource = o.params.dataSource || ''
          this.dtType = o.params.dtType || ''
          this.datatarget = o.params.dataTarget || ''
          this.sql = o.params.sql || ''
          this.sourceTable = o.params.sourceTable || ''
          this.targetTable = o.params.targetTable || ''
          this.jobSpeedByte = '' + (o.params.jobSpeedByte / 1024 || 0)
          this.jobSpeedRecord = '' + (o.params.jobSpeedRecord || 0)
          this.preStatements = o.params.preStatements || []
          this.postStatements = o.params.postStatements || []
          this.targetCloumns = o.params.targetCloumns || []
          this.sourceCloumns = o.params.sourceCloumns || []
        } else {
          this.customConfig = 1
          this.enable = true
          this.json = o.params.json || []
          this.localParams = o.params.localParams || ''
        }
      }
      if(this.taskType === 'INPUT' || this.taskType === 'OUTPUT'){
        let type = this.taskType === 'INPUT' ? 'source' : 'target';
        if(this.dsType || this.dtType){
          this.datasourceTypeChange(type , true);
        }
        if(this.datatarget || this.datasource){
          this.datasourceChange(type , true);
        }
        if(this.targetTable || this.sourceTable){
          this.tableChange(type);
        }
      }
    },
    mounted () {
      if(this.taskType === 'DATAX'){
        if (this.customConfig) {
          setTimeout(() => {
            this._handlerJsonEditor()
          }, 200)
        } else {
          setTimeout(() => {
            this._handlerEditor()
          }, 200)
        }
      }
    },
    destroyed () {
      /**
       * Destroy the editor instance
       */
      if (editor) {
        editor.toTextArea() // Uninstall
        editor.off($('.code-sql-mirror'), 'keypress', this.keypress)
      }
      if (jsonEditor) {
        jsonEditor.toTextArea() // Uninstall
        jsonEditor.off($('.code-json-mirror'), 'keypress', this.keypress)
      }
    },
    watch: {
      // Watch the cacheParams
      cacheParams (val) {
        this._cacheParams()
      }
    },
    computed: {
      cacheParams () {
        return {
          dsType: this.dsType,
          dataSource: this.datasource,
          dtType: this.dtType,
          dataTarget: this.datatarget,
          sourceTable: this.sourceTable,
          targetTable: this.targetTable,
          jobSpeedByte: parseInt(this.jobSpeedByte) * 1024,
          jobSpeedRecord: parseInt(this.jobSpeedRecord),
          preStatements: this.preStatements,
          postStatements: this.postStatements
        }
      },
      cType(){
        return this.taskType === 'INPUT' ? 'source' : 'target';
      }
    },
    components: { mListBox, mDatasource, mLocalParams, mStatementList, mSelectInput, mScriptBox }
  }
</script>
